package com.jic.veteran.portal.service.impl;

import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Sets;
import com.jic.veteran.mapper.ProjectBasicMapper;
import com.jic.veteran.mapper.ProjectImplementMapper;
import com.jic.veteran.model.ProjectBasic;
import com.jic.veteran.model.ProjectBasicExample;
import com.jic.veteran.model.ProjectImplement;
import com.jic.veteran.model.ProjectImplementExample;
import com.jic.veteran.portal.domain.ProjectBasicQueryParam;
import com.jic.veteran.portal.domain.ProjectDonationTotalDto;
import com.jic.veteran.portal.domain.ProjectDto;
import com.jic.veteran.portal.service.ProjectDonationService;
import com.jic.veteran.portal.service.ProjectService;
import com.jic.veteran.portal.service.UmsMemberCacheService;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class ProjectServiceImpl implements ProjectService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ProjectServiceImpl.class);

    @Autowired
    private ProjectBasicMapper projectBasicMapper;
    @Autowired
    private ProjectImplementMapper projectImplementMapper;
    @Autowired
    private UmsMemberCacheService umsMemberCacheService;
    @Autowired private ProjectDonationService projectDonationService;

    @Override
    public List<ProjectBasic> listAll() {
        List<ProjectBasic> projectBasicList = umsMemberCacheService.getProjectList();
        if(null == projectBasicList || projectBasicList.size() == 0) {
            ProjectBasicExample projectBasicExample = new ProjectBasicExample();
            projectBasicExample.createCriteria().andProjectStatusEqualTo(1);
            projectBasicList = projectBasicMapper.selectByExample(projectBasicExample);
            if(!projectBasicList.isEmpty()) {
                umsMemberCacheService.setProjectDtoList(projectBasicList);
            }
        }
        this.fillDonationTotalInfo(projectBasicList);
        return projectBasicList;
    }

    @Override
    public List<ProjectBasic> list(ProjectBasicQueryParam projectBasicQueryParam, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum,pageSize);
        ProjectBasicExample projectBasicExample = new ProjectBasicExample();
        if(StrUtil.isNotEmpty(projectBasicQueryParam.getProjectId())) {
            projectBasicExample.createCriteria().andProjectIdEqualTo(projectBasicQueryParam.getProjectId());
        }
        if(StrUtil.isNotEmpty(projectBasicQueryParam.getProjectName())) {
            projectBasicExample.createCriteria().andProjectNameLike("%" + projectBasicQueryParam.getProjectName() + "%");
        }
        if(NumberUtil.isNumber(projectBasicQueryParam.getProjectStatus())) {
            projectBasicExample.createCriteria().andProjectStatusEqualTo(Integer.valueOf(projectBasicQueryParam.getProjectStatus()));
        }
        if(StrUtil.isNotEmpty(projectBasicQueryParam.getCreateTime())) {
            projectBasicExample.createCriteria()
                    .andStartTimeLessThanOrEqualTo(DateUtil.parse(projectBasicQueryParam.getCreateTime()))
                    .andEndTimeGreaterThanOrEqualTo(DateUtil.parse(projectBasicQueryParam.getCreateTime()));
        }
        projectBasicExample.createCriteria().andProjectStatusEqualTo(1);
        List<ProjectBasic> projectBasicList = projectBasicMapper.selectByExampleWithBLOBs(projectBasicExample);
        this.fillDonationTotalInfo(projectBasicList);
        return projectBasicList;
    }

    @Override
    public JSONObject getItem(Long id) {
        String dto = umsMemberCacheService.getProject(id);
        if(null == dto) {
            ProjectBasicExample projectBasicExample = new ProjectBasicExample();
            projectBasicExample.createCriteria().andIdEqualTo(id);
            projectBasicExample.createCriteria().andProjectStatusEqualTo(1);
            List<ProjectBasic> projectBasicList = projectBasicMapper.selectByExampleWithBLOBs(projectBasicExample);
            if(!projectBasicList.isEmpty()) {
                ProjectBasic projectBasic = projectBasicList.get(0);
                ProjectDto projectDto = new ProjectDto();
                projectDto.setProjectBasic(projectBasic);
                ProjectImplementExample projectImplementExample = new ProjectImplementExample();
                projectImplementExample.createCriteria().andProjectIdEqualTo(projectBasic.getProjectId());
                List<ProjectImplement> projectImplements = projectImplementMapper.selectByExampleWithBLOBs(projectImplementExample);
                if (!projectImplements.isEmpty()) {
                    projectDto.setProjectImplement(projectImplements.get(0));
                }
                umsMemberCacheService.setProject( projectDto);
                return JSONUtil.parseObj(projectDto);
            }
        }
        JSONObject jsonObject = JSONUtil.parseObj(dto);
//        jsonObject.setDateFormat("yyyy-MM-dd HH:mm:ss");
        return jsonObject;
    }

    @Override
    public JSONObject getItemByProjectId(String projectId) {
        String dto = umsMemberCacheService.getProjectByProjectId(projectId);
        if(null == dto) {
            ProjectBasicExample projectBasicExample = new ProjectBasicExample();
            projectBasicExample.createCriteria().andProjectIdEqualTo(projectId);
            projectBasicExample.createCriteria().andProjectStatusEqualTo(1);
            List<ProjectBasic> projectBasicList = projectBasicMapper.selectByExampleWithBLOBs(projectBasicExample);
            if(!projectBasicList.isEmpty()) {
                ProjectBasic projectBasic = projectBasicList.get(0);
                ProjectDto projectDto = new ProjectDto();
                projectDto.setProjectBasic(projectBasic);
                ProjectImplementExample projectImplementExample = new ProjectImplementExample();
                projectImplementExample.createCriteria().andProjectIdEqualTo(projectBasic.getProjectId());
                List<ProjectImplement> projectImplements = projectImplementMapper.selectByExampleWithBLOBs(projectImplementExample);
                if (!projectImplements.isEmpty()) {
                    projectDto.setProjectImplement(projectImplements.get(0));
                }
                umsMemberCacheService.setProject(projectDto);
                return JSONUtil.parseObj(projectDto);
            }
        }
        JSONObject jsonObject = JSONUtil.parseObj(dto);
//        jsonObject.setDateFormat("yyyy-MM-dd HH:mm:ss");
        return jsonObject;
    }

    @Override
    public JSONObject getProjectBasic(String projectId) {
        JSONObject projectDto = this.getItemByProjectId(projectId);
        if (null != projectDto && projectDto.containsKey("projectBasic")) {
            return (JSONObject) projectDto.get("projectBasic");
        }
        return null;
    }

    @Override
    public JSONObject getProjectImplement(String projectId) {
        JSONObject jsonObject = this.getItemByProjectId(projectId);
        if(jsonObject.containsKey("projectImplement")) {
            return (JSONObject) jsonObject.get("projectImplement");
        }
        return null;
    }

  @Override
  public ProjectDonationTotalDto getActualFundingByProjectId(String projectId) {
    if (StrUtil.isBlank(projectId)) {
      return null;
    }
    List<ProjectDonationTotalDto> totalDtoList
        = projectDonationService.getDonateTotalByProjectIds(Sets.newHashSet(projectId));
    if (ObjectUtil.isEmpty(totalDtoList)) {
      return null;
    }
    return totalDtoList.get(0);
  }

  /**
   * 填充总捐款金额和人次.
   *
   * @param projectBasicList project basic list
   */
  private void fillDonationTotalInfo(List<ProjectBasic> projectBasicList) {
    if (projectBasicList == null || projectBasicList.size() <= 0) {
      return;
    }
    Set<String> projectIds = projectBasicList.parallelStream()
                                             .map(ProjectBasic::getProjectId)
                                             .collect(toSet());

    List<ProjectDonationTotalDto> totalDtoList
        = projectDonationService.getDonateTotalByProjectIds(projectIds);
    Map<String, ProjectDonationTotalDto> totalDtoMap
        = totalDtoList.parallelStream()
                      .collect(toMap(
                          ProjectDonationTotalDto::getProjectId,
                          dto -> dto));
    BigDecimal zero = new BigDecimal("0.00");
    projectBasicList.parallelStream()
                    .forEach(pb -> {
                      String pid = pb.getProjectId();
                      ProjectDonationTotalDto dto = totalDtoMap.get(pid);
                      if (dto == null) {
                        pb.setProjectActualFunding(zero);
                        pb.setDonationCount(0);
                        return;
                      }
                      pb.setProjectActualFunding(dto.getProjectActualFunding());
                      pb.setDonationCount(dto.getDonationCount());
                    });
  }
}
